package com.droidlogic.setupwizard.fragment;

import android.content.ComponentName;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
import android.graphics.drawable.Drawable;
import android.os.Bundle;
import android.os.IBinder;
import android.provider.Settings;
import android.service.dreams.DreamService;
import android.text.format.DateUtils;
import android.util.Log;

import androidx.annotation.NonNull;
import androidx.core.content.ContextCompat;
import androidx.fragment.app.FragmentManager;
import androidx.leanback.app.GuidedStepSupportFragment;
import androidx.leanback.widget.GuidanceStylist;
import androidx.leanback.widget.GuidedAction;
import androidx.leanback.widget.GuidedActionsStylist;

import com.droidlogic.setupwizard.R;
import com.droidlogic.setupwizard.leanback.timepicker.GuidedActionsStylistExtended;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.List;

public class ScreenSaverFragment extends BaseGuideStepFragment {

    private static final int DAYDREAMS_SELECT = 40;
    private static final int DAYDREAMS_SELECT_OFFSET = 1000;
    private static final int DAYDREAMS_SLEEP = 41;
    private static final int DAYDREAMS_SLEEP_OFFSET = 100;
    private static final int DAYDREAMS_TEST = 42;

    @Override
    public GuidedActionsStylist onCreateActionsStylist() {
        return new GuidedActionsStylistExtended();
    }

    public static ScreenSaverFragment newInstance(final int option) {
        final ScreenSaverFragment f = new ScreenSaverFragment();
        final Bundle args = new Bundle();
        f.setArguments(args);
        return f;
    }

    @Override
    String getNextActionLabel() {
        return getString(R.string.action_next);
    }

    @Override
    public void onNextAction() {
        FragmentManager fm = getParentFragmentManager();
        DateTimeFragment next = DateTimeFragment.newInstance(getSelectedActionPosition() - 1);
        GuidedStepSupportFragment.add(fm, next);
    }

    @Override
    @NonNull
    public GuidanceStylist.Guidance onCreateGuidance(Bundle savedInstanceState) {
        String title = getString(R.string.daydreams);
        String breadcrumb = "";
        String description = getString(R.string.daydreams_description);
        Drawable icon = ContextCompat.getDrawable(getActivity(), R.drawable.screensaver);
        return new GuidanceStylist.Guidance(title, description, breadcrumb, icon);
    }

//    List<Map<String, Object>> zonesList;
    String[] sleep_timeout_entries;
    String[] sleep_timeout_values;
    GuidedAction sleepGuidedAction;
    GuidedAction currentSleepGuidedAction;


    List<ResolveInfo> mDreamInfos;
    GuidedAction daydreamsGuidedAction;
    GuidedAction currentDaydreamsGuidedAction;
    PackageManager pm ;
    @Override
    public void onCreateActions(@NonNull List<GuidedAction> actions, Bundle savedInstanceState) {
        if (getContext() == null) return;

        pm = getContext().getPackageManager();
        initDreamReflection();
        currentDaydreamsGuidedAction = null;
        mDreamInfos = getDreamInfos();
        ComponentName dream = getActiveDream();
        List<GuidedAction> day_dreams = new ArrayList<>();
        for(int i = 0;i<mDreamInfos.size();i++){
            ResolveInfo resolveInfo = mDreamInfos.get(i);
            boolean check = false;
            if(dream != null){
                ComponentName tmp = getDreamComponentName(resolveInfo);
                if (tmp != null && dream.equals(tmp)) {
                    check = true;
                }
            }
            CharSequence caption = resolveInfo.loadLabel(pm);
            GuidedAction guidedAction = addCheckedAction(getActivity(), day_dreams, DAYDREAMS_SELECT_OFFSET+i , caption.toString(),null, check);
            if(check)
                currentDaydreamsGuidedAction = guidedAction;
        }
        daydreamsGuidedAction = new GuidedAction.Builder(getActivity())
                .id(DAYDREAMS_SELECT)
                .title(R.string.daydreams_select)
                .subActions(day_dreams)
                .build();
        if(currentDaydreamsGuidedAction != null){
            daydreamsGuidedAction.setDescription(currentDaydreamsGuidedAction.getTitle());
        }

        actions.add(daydreamsGuidedAction);


        currentSleepGuidedAction = null;

        sleep_timeout_entries = getResources().getStringArray(R.array.device_energy_saver_sleep_timeout_entries);
        sleep_timeout_values = getResources().getStringArray(R.array.device_energy_saver_sleep_timeout_values);
        int daytime = getDreamTime();
        List<GuidedAction> sleep_timeout = new ArrayList<>();
        for(int i=0;i<sleep_timeout_values.length;i++){
            boolean check = (daytime == Integer.parseInt(sleep_timeout_values[i]));
            GuidedAction guidedAction = addCheckedAction(getActivity(), sleep_timeout, DAYDREAMS_SLEEP_OFFSET+i , String.valueOf(sleep_timeout_entries[i]),null, check);

            if(check)
                currentSleepGuidedAction = guidedAction;
        }

        sleepGuidedAction = new GuidedAction.Builder(getActivity())
                .id(DAYDREAMS_SELECT)
                .title(R.string.daydreams_sleep)
                .subActions(sleep_timeout)
                .build();
        if(currentSleepGuidedAction != null){
            sleepGuidedAction.setDescription(currentSleepGuidedAction.getTitle());
        }
        actions.add(sleepGuidedAction);
        //addAction(getContext(), actions, CONTINUE, getString(R.string.action_start), getString(R.string.complete_setup));


        GuidedAction active = new GuidedAction.Builder(getActivity())
                .title(getString(R.string.daydreams_test))
                .id(DAYDREAMS_TEST)
                .build();
        actions.add(active);
    }

    @Override
    public void onGuidedActionClicked(GuidedAction action) {
        if (action.getId() == DAYDREAMS_TEST) {
            activeDream();
        }
    }
    @Override
    public boolean onSubGuidedActionClicked(GuidedAction action) {
        try {
            int id = (int) action.getId();
            Log.v("sjf","onSubGuidedActionClicked id:"+id);
            if(id >= DAYDREAMS_SELECT_OFFSET){
                ResolveInfo dream = mDreamInfos.get(id - DAYDREAMS_SELECT_OFFSET);
                setActiveDream(dream);
                postDelayed(() -> {
                    daydreamsGuidedAction.setDescription(action.getTitle());
                    notifyActionChanged(0);
                    }, 350);

                if (currentDaydreamsGuidedAction != null) {
                    currentDaydreamsGuidedAction.setChecked(false);
                }
                action.setChecked(true);
                currentDaydreamsGuidedAction = action;
            }else if(id >= DAYDREAMS_SLEEP_OFFSET){
                String sleep_timeout = sleep_timeout_values[id-DAYDREAMS_SLEEP_OFFSET];
                setDreamTime(Integer.parseInt(sleep_timeout));
                postDelayed(() -> {
                        sleepGuidedAction.setDescription(action.getTitle());
                        notifyActionChanged(1);
                    }, 350);

                if (currentSleepGuidedAction != null) {
                    currentSleepGuidedAction.setChecked(false);
                }
                action.setChecked(true);
                currentSleepGuidedAction = action;
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return super.onSubGuidedActionClicked(action);
    }

    private static final int DEFAULT_DREAM_TIME_MS = (int) (30 * DateUtils.MINUTE_IN_MILLIS);
    private int getDreamTimeId(String daytime) {
        for(int i=0;i<sleep_timeout_values.length;i++){
            if(daytime.equals(sleep_timeout_entries[i])){
                return i;
            }
        }
        return -1;
    }
    private int getDreamTime() {
        return Settings.System.getInt(getActivity().getContentResolver(), Settings.System.SCREEN_OFF_TIMEOUT,
                DEFAULT_DREAM_TIME_MS);
    }

    private void setDreamTime(int ms) {
        Settings.System.putInt(getActivity().getContentResolver(), Settings.System.SCREEN_OFF_TIMEOUT, ms);
    }
    public static final String DREAM_SERVICE = "dreams";
    private Object mDreamManager;
    private Method getDreamComponents;
    private Method setDreamComponents;
    private Method awaken;
    private Method dream;
    private void initDreamReflection() {
        try {
            Class IDreamManager = ClassLoader.getSystemClassLoader().loadClass("android.service.dreams.IDreamManager");
            Class IDreamManager$Stub = Class.forName("android.service.dreams.IDreamManager$Stub");
            Method asInterface = IDreamManager$Stub.getDeclaredMethod("asInterface", IBinder.class);
            asInterface.setAccessible(true);
            IBinder iBinder = null;
            Class<?> clz = Class.forName("android.os.ServiceManager");
            Method getService = clz.getMethod("getService", String.class);
            getService.setAccessible(true);
            iBinder = (IBinder) getService.invoke(null, DREAM_SERVICE);
            mDreamManager = asInterface.invoke(null, iBinder);
            getDreamComponents = IDreamManager.getDeclaredMethod("getDreamComponents");
            getDreamComponents.setAccessible(true);
            setDreamComponents = IDreamManager.getDeclaredMethod("setDreamComponents", (new ComponentName[0]).getClass());
            setDreamComponents.setAccessible(true);
            awaken = IDreamManager.getDeclaredMethod("awaken");
            awaken.setAccessible(true);

            dream = IDreamManager.getDeclaredMethod("dream");
            dream.setAccessible(true);
        } catch (ClassNotFoundException | NoSuchMethodException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (InvocationTargetException e) {
            e.printStackTrace();
        }
    }

    public void activeDream() {
        Log.v("sjf","activeDream");
        try {
            dream.invoke(mDreamManager);
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (InvocationTargetException e) {
            e.printStackTrace();
        }
    }

    /**
     * 获取当前屏保的包名信息
     *
     * @return
     */
    public ComponentName getActiveDream() {
        try {
            ComponentName[] dreams = (ComponentName[]) getDreamComponents.invoke(mDreamManager);
            return dreams != null && dreams.length > 0 ? dreams[0] : null;
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (InvocationTargetException e) {
            e.printStackTrace();
        }
        return null;

    }

    /**
     * 获取当前屏保包名信息列表
     *
     * @return
     */
    public List<ResolveInfo> getDreamInfos() {
        PackageManager pm = getContext().getPackageManager();
        Intent dreamIntent = new Intent(DreamService.SERVICE_INTERFACE);
        List<ResolveInfo> resolveInfos = pm.queryIntentServices(dreamIntent,
                PackageManager.GET_META_DATA);
        return resolveInfos;
    }

    public void setActiveDream(ResolveInfo info) {
        ComponentName dream = getDreamComponentName(info);
        ComponentName[] dreams = new ComponentName[]{dream};
        try {
            setDreamComponents.invoke(mDreamManager, new Object[]{dream == null ? null : dreams});
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (InvocationTargetException e) {
            e.printStackTrace();
        }
    }

    private ComponentName getDreamComponentName(ResolveInfo resolveInfo) {
        if (resolveInfo == null || resolveInfo.serviceInfo == null)
            return null;
        return new ComponentName(resolveInfo.serviceInfo.packageName, resolveInfo.serviceInfo.name);
    }
}
